1   package org.apache.lucene.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one or more
5    * contributor license agreements.  See the NOTICE file distributed with
6    * this work for additional information regarding copyright ownership.
7    * The ASF licenses this file to You under the Apache License, Version 2.0
8    * (the "License"); you may not use this file except in compliance with
9    * the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  import java.util.Arrays;
21  
22  /**
23   * Estimates how {@link RamUsageEstimator} estimates physical memory consumption
24   * of Java objects. 
25   */
26  public class StressRamUsageEstimator extends LuceneTestCase {
27    static class Entry {
28      Object o;
29      Entry next;
30  
31      public Entry createNext(Object o) {
32        Entry e = new Entry();
33        e.o = o;
34        e.next = next;
35        this.next = e;
36        return e;
37      }
38    }
39  
40    volatile Object guard;
41    
42    // This shows an easy stack overflow because we're counting recursively.
43    public void testLargeSetOfByteArrays() {
44  
45      System.gc();
46      long before = Runtime.getRuntime().totalMemory();
47      Object [] all = new Object [1000000]; 
48      for (int i = 0; i < all.length; i++) {
49        all[i] = new byte[random().nextInt(3)];
50      }
51      System.gc();
52      long after = Runtime.getRuntime().totalMemory();
53      System.out.println("mx:  " + RamUsageEstimator.humanReadableUnits(after - before));
54      System.out.println("rue: " + RamUsageEstimator.humanReadableUnits(shallowSizeOf(all)));
55  
56      guard = all;
57    }
58   
59    private long shallowSizeOf(Object[] all) {
60      long s = RamUsageEstimator.shallowSizeOf(all);
61      for (Object o : all) {
62        s+= RamUsageEstimator.shallowSizeOf(o);
63      }
64      return s;
65    }
66  
67    private long shallowSizeOf(Object[][] all) {
68      long s = RamUsageEstimator.shallowSizeOf(all);
69      for (Object[] o : all) {
70        s += RamUsageEstimator.shallowSizeOf(o);
71        for (Object o2 : o) {
72          s += RamUsageEstimator.shallowSizeOf(o2);
73        }
74      }
75      return s;
76    }
77  
78    public void testSimpleByteArrays() {
79      Object [][] all = new Object [0][];
80      try {
81        while (true) {
82          // Check the current memory consumption and provide the estimate.
83          System.gc();
84          long estimated = shallowSizeOf(all);
85          if (estimated > 50 * RamUsageEstimator.ONE_MB) {
86            break;
87          }
88  
89          // Make another batch of objects.
90          Object[] seg =  new Object[10000];
91          all = Arrays.copyOf(all, all.length + 1);
92          all[all.length - 1] = seg;
93          for (int i = 0; i < seg.length; i++) {
94            seg[i] = new byte[random().nextInt(7)];
95          }
96        }
97      } catch (OutOfMemoryError e) {
98        // Release and quit.
99      }
100   }
101 }